package com.ikingtech.platform.service.system.post.controller;

import com.ikingtech.framework.sdk.base.model.BatchParam;
import com.ikingtech.framework.sdk.base.model.DragOrderParam;
import com.ikingtech.framework.sdk.context.event.TenantDeleteEvent;
import com.ikingtech.framework.sdk.context.security.Me;
import com.ikingtech.framework.sdk.context.exception.FrameworkException;
import com.ikingtech.framework.sdk.core.response.R;
import com.ikingtech.framework.sdk.data.helper.DragHelper;
import com.ikingtech.framework.sdk.data.helper.DragHelperBuilder;
import com.ikingtech.framework.sdk.enums.common.DragTargetPositionEnum;
import com.ikingtech.framework.sdk.post.api.PostApi;
import com.ikingtech.framework.sdk.post.api.PostUserApi;
import com.ikingtech.framework.sdk.post.model.PostDTO;
import com.ikingtech.framework.sdk.post.model.PostQueryParamDTO;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.framework.sdk.web.annotation.ApiController;
import com.ikingtech.platform.service.system.post.entity.PostDO;
import com.ikingtech.platform.service.system.post.exception.PostExceptionInfo;
import com.ikingtech.platform.service.system.post.service.PostService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author tie yan
 */
@RequiredArgsConstructor
@ApiController(value = "/system/post", name = "系统管理-岗位管理", description = "系统管理-岗位管理")
public class PostController implements PostApi {

    private final PostService service;

    private final PostUserApi postUserApi;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<String> add(PostDTO post) {
        if (Boolean.TRUE.equals(this.service.nameExist(post.getName()))) {
            throw new FrameworkException(PostExceptionInfo.DUPLICATE_POST_NAME);
        }
        PostDO entity = Tools.Bean.copy(post, PostDO.class);
        entity.setId(Tools.Id.uuid());
        entity.setSortOrder(this.service.getMaxSortOrder());
        entity.setTenantCode(Me.tenantCode());
        this.service.save(entity);
        return R.ok(entity.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Object> delete(String id) {
        this.service.removeById(id);
        this.postUserApi.deleteUserPost(id);
        return R.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Object> update(PostDTO post) {
        if (!Boolean.TRUE.equals(this.service.exist(post.getId()))) {
            throw new FrameworkException(PostExceptionInfo.POST_NOT_FOUND);
        }
        if (Boolean.TRUE.equals(this.service.nameExist(post.getId(), post.getName()))) {
            throw new FrameworkException(PostExceptionInfo.DUPLICATE_POST_NAME);
        }
        this.service.updateById(Tools.Bean.copy(post, PostDO.class));
        return R.ok();
    }

    @Override
    public R<List<PostDTO>> page(PostQueryParamDTO queryParam) {
        return R.ok(this.service.listPage(queryParam, Me.tenantCode()).convert(entity -> Tools.Bean.copy(entity, PostDTO.class)));
    }

    @Override
    public R<List<PostDTO>> all() {
        return R.ok(Tools.Coll.convertList(this.service.listByTenantCode(Me.tenantCode()), entity -> Tools.Bean.copy(entity, PostDTO.class)));
    }

    @Override
    public R<PostDTO> detail(String id) {
        PostDO entity = this.service.getById(id);
        if (null == entity) {
            throw new FrameworkException(PostExceptionInfo.POST_NOT_FOUND);
        }
        return R.ok(Tools.Bean.copy(entity, PostDTO.class));
    }

    @Override
    public R<List<PostDTO>> listByName(String name) {
        return R.ok(Tools.Coll.convertList(this.service.listByName(name, Me.tenantCode()), entity -> Tools.Bean.copy(entity, PostDTO.class)));
    }

    @Override
    public R<Map<String, PostDTO>> mapByIds(BatchParam<String> ids) {
        if (Tools.Coll.isBlank(ids.getList())) {
            return R.ok(new HashMap<>());
        }
        return R.ok(Tools.Coll.convertMap(this.service.listByIdsAndTenantCode(ids.getList(), Me.tenantCode()), PostDO::getId, entity -> Tools.Bean.copy(entity, PostDTO.class)));
    }

    @Override
    public R<Object> drag(DragOrderParam dragParam) {
        DragHelper<PostDO> dragHelper = DragHelperBuilder.builder(this.service::between)
                .which(dragParam.getParentId(), dragParam.getTargetParentId(), DragTargetPositionEnum.INNER.equals(dragParam.getPosition()))
                .currentNode(() -> this.service.getById(dragParam.getCurrentId()))
                .targetNode(() -> this.service.getById(dragParam.getTargetId()))
                .maxSortOrder(this.service::getMaxSortOrder)
                .beforeTarget(DragTargetPositionEnum.BEFORE.equals(dragParam.getPosition()))
                .build();
        this.service.updateBatchById(dragHelper.drag());
        return R.ok();
    }

    @EventListener
    public void deleteTenantPostEventListener(TenantDeleteEvent event) {
        this.service.removeByTenantCode(event.getCode());
    }
}
